<html>
<head><meta charset="utf-8"><title>Unsafe Policy: does all foreign code count as &quot;an unsafe ... · t-lang/wg-unsafe-code-guidelines · Zulip Chat Archive</title></head>
<h2>Stream: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/index.html">t-lang/wg-unsafe-code-guidelines</a></h2>
<h3>Topic: <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html">Unsafe Policy: does all foreign code count as &quot;an unsafe ...</a></h3>

<hr>

<base href="https://rust-lang.zulipchat.com">

<head><link href="https://rust-lang.github.io/zulip_archive/style.css" rel="stylesheet"></head>

<a name="189352681"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189352681" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189352681">(Feb 28 2020 at 21:25)</a>:</h4>
<p>Here is some example code:</p>
<p><a href="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=7841ef908f534ef11daca616a16cc0b9" target="_blank" title="https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=7841ef908f534ef11daca616a16cc0b9">https://play.rust-lang.org/?version=stable&amp;mode=debug&amp;edition=2018&amp;gist=7841ef908f534ef11daca616a16cc0b9</a></p>
<p>My question is: are the unsafe blocks here actually properly justified? Should we consider it a sound construction?</p>
<p>Suppose you had some other function like this:</p>
<div class="codehilite"><pre><span></span><span class="cp">#[no_mangle]</span><span class="w"></span>
<span class="k">pub</span><span class="w"> </span><span class="k">extern</span><span class="w"> </span><span class="s">&quot;C&quot;</span><span class="w"> </span><span class="k">fn</span> <span class="nf">foo</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="o">&gt;</span><span class="p">(</span><span class="n">sli</span>: <span class="nc">CSharedSlice</span><span class="o">&lt;</span><span class="na">&#39;a</span><span class="p">,</span><span class="w"> </span><span class="kt">u8</span><span class="o">&gt;</span><span class="p">)</span><span class="w"> </span><span class="p">{</span><span class="w"></span>
<span class="w">  </span><span class="n">println</span><span class="o">!</span><span class="p">(</span><span class="s">&quot;the length is {}&quot;</span><span class="p">,</span><span class="w"> </span><span class="n">sli</span><span class="p">.</span><span class="n">to_slice</span><span class="p">().</span><span class="n">len</span><span class="p">())</span><span class="w"></span>
<span class="p">}</span><span class="w"></span>
</pre></div>


<p>And a bit of C code calls this function with a totally zeroed struct and UB happens.</p>
<p>If there is UB, it's a bug in the compiler or an unsafe block was used improperly. This is the rule we always live by.</p>
<p>In this case, some C code did the thing which broke the contract of the function and lead to UB. Do we consider the C code to be the improper unsafe block? Because it's still impossible to make <code>foo</code> trigger UB from safe Rust, so it should still be considered sound.</p>



<a name="189358224"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189358224" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189358224">(Feb 28 2020 at 22:37)</a>:</h4>
<p>The original "unsafe block" that is to blame for the UB is the one that invoked the C code that eventually called your function with invalid arguments.</p>



<a name="189358301"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189358301" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189358301">(Feb 28 2020 at 22:38)</a>:</h4>
<p>If your code is a library and the program is in C, then you can just blame the user for the UB since it's his fault he decided to run a C program <span aria-label="mischievous" class="emoji emoji-1f61b" role="img" title="mischievous">:mischievous:</span></p>



<a name="189358348"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189358348" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Amanieu <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189358348">(Feb 28 2020 at 22:39)</a>:</h4>
<p>But seriously, I would consider your code perfectly sound as it is.</p>



<a name="189358858"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189358858" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189358858">(Feb 28 2020 at 22:48)</a>:</h4>
<p>Yeah, okay. Might put the full form of this into a crate for easy reference.</p>



<a name="189360153"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189360153" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Dylan MacKenzie (ecstatic-morse) <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189360153">(Feb 28 2020 at 23:06)</a>:</h4>
<p>(deleted)</p>



<a name="189382701"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189382701" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189382701">(Feb 29 2020 at 08:52)</a>:</h4>
<div class="codehilite"><pre><span></span>    // Safety: Safe rust can never construct this type
    // with incorrect fields, so we can trust the fields.
</pre></div>


<p><span class="user-mention" data-user-id="224471">@Lokathor</span> sounds like your type <code>CSharedSlice</code> has some invariant about these fields attached to it.<br>
If you are using "SAFETY:" comments, I think it is a good idea to explicitly write down that invariant in a comment at the type definition. Then "SAFETY" comments elsewhere, like in <code>to_slice</code> can refer to that invariant.<br>
The comment you have there right now is very non-local: this one safety comment suddenly means I need to re-read all the rest of this code to check that what it says is correct. SAFETY comments should be <em>locally</em> checkable.</p>



<a name="189391494"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189391494" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189391494">(Feb 29 2020 at 14:02)</a>:</h4>
<p>Well the safety section is the entire safety section of core::slice::from_raw_parts</p>



<a name="189394155"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189394155" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189394155">(Feb 29 2020 at 15:29)</a>:</h4>
<p>Fundamentally you can't rely on module privacy and then also have local checks</p>



<a name="189400250"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189400250" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189400250">(Feb 29 2020 at 18:35)</a>:</h4>
<p><span class="user-mention silent" data-user-id="224471">Lokathor</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E/near/189394155" title="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E/near/189394155">said</a>:</p>
<blockquote>
<p>Fundamentally you can't rely on module privacy and then also have local checks</p>
</blockquote>
<p>not sure why you'd say that</p>



<a name="189400256"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189400256" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189400256">(Feb 29 2020 at 18:36)</a>:</h4>
<p>but when we formally prove things like RefCell correct, we do everything locally as we'd prefer not to go crazy</p>



<a name="189400308"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189400308" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189400308">(Feb 29 2020 at 18:36)</a>:</h4>
<p>the key point is to put everything global that you might need into the invariant -- because then you can locally check that you always maintain the invariant, and you get to locally <em>assume</em> that everything else follows the invariant, and thus you never need to think about more than one line of code at a time (once the invariant is set)</p>



<a name="189400313"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189400313" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189400313">(Feb 29 2020 at 18:37)</a>:</h4>
<p>when I saw such proofs for the first time my mind was kind of blown :D</p>



<a name="189400362"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189400362" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189400362">(Feb 29 2020 at 18:38)</a>:</h4>
<p>with the current state of the art in formal methods, we can do entirely local proofs (local in "time and space") of the craziest concurrent data structures, and we can do it machine-checked in Coq :)</p>



<a name="189420443"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189420443" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189420443">(Mar 01 2020 at 05:28)</a>:</h4>
<p>Well, assuming that you mean locally to be like, "in the current function", then I don't know how you can possibly locally check an invariant such as "the length value is correct for the allocation associated with this pointer so we can make this slice".</p>



<a name="189420494"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189420494" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189420494">(Mar 01 2020 at 05:30)</a>:</h4>
<p>But, to "zoom out" a bit, there is now a proper draft of this code available on github, &lt;<a href="https://github.com/Lokathor/chromium/blob/master/src/c_shared_slice.rs" target="_blank" title="https://github.com/Lokathor/chromium/blob/master/src/c_shared_slice.rs">https://github.com/Lokathor/chromium/blob/master/src/c_shared_slice.rs</a>&gt; and I'll add the mutable version tomorrow and put it out as a 0.0.1 if things look good.</p>



<a name="189442298"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189442298" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189442298">(Mar 01 2020 at 18:17)</a>:</h4>
<p><span class="user-mention silent" data-user-id="224471">Lokathor</span> <a href="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E/near/189420443" title="#narrow/stream/136281-t-lang.2Fwg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E/near/189420443">said</a>:</p>
<blockquote>
<p>Well, assuming that you mean locally to be like, "in the current function", then I don't know how you can possibly locally check an invariant such as "the length value is correct for the allocation associated with this pointer so we can make this slice".</p>
</blockquote>
<p>you have to <em>declare</em> the invariant once, globally. and then you, roughly speaking, check locally at each line that it is maintained.</p>



<a name="189442522"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189442522" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> Lokathor <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189442522">(Mar 01 2020 at 18:23)</a>:</h4>
<p>I agree with that, but I also absolutely wouldn't call it "locally checkable"</p>



<a name="189478093"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189478093" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189478093">(Mar 02 2020 at 10:25)</a>:</h4>
<p>hm. well "local" ("in time and space") is the/a standard term for this in the academic literature, but I am open to alternative suggestions ;)</p>



<a name="189478154"></a>
<h4><a href="https://rust-lang.zulipchat.com#narrow/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe%20Policy%3A%20does%20all%20foreign%20code%20count%20as%20%22an%20unsafe%20.../near/189478154" class="zl"><img src="https://rust-lang.github.io/zulip_archive/assets/img/zulip.svg" alt="view this post on Zulip" style="width:20px;height:20px;"></a> RalfJ <a href="https://rust-lang.github.io/zulip_archive/stream/136281-t-lang/wg-unsafe-code-guidelines/topic/Unsafe.20Policy.3A.20does.20all.20foreign.20code.20count.20as.20.22an.20unsafe.20.2E.2E.2E.html#189478154">(Mar 02 2020 at 10:26)</a>:</h4>
<p>there are other proof methods where verifying one thread requires checking something <em>specific to this thread</em> about all the other threads -- that is then not "local" any more</p>



<hr><p>Last updated: Aug 07 2021 at 22:04 UTC</p>
</html>